﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Reborn_WorldServer;
using Reborn_Server.App1AppHandler;
using System.Drawing;

namespace App1AppHandler
{
    public class Creature_WaveSummoner : Creature
    {
        public Creature_WaveSummoner(AppHandler2 gameHandler) : base(gameHandler) { }

        public override void runAI()
        {
            base.runAI();

            checkSpawns();
        }

        public override int HP
        {
            set
            {
                base.HP = value;

                if (value < 1)
                    resetSpawnWaves();
            }
            get
            {
                return base.HP;
            }
        }

        private void resetSpawnWaves()
        {
            noRound1SpawnsTill = DateTime.Now;
            noRound2SpawnsTill = DateTime.Now;
            noRound3SpawnsTill = DateTime.Now;

            currentNumRound1Spawns = 0;
            currentNumRound2Spawns = 0;
            currentNumRound3Spawns = 0;
        }

        private DateTime noRound1SpawnsTill = DateTime.Now;
        private DateTime noRound2SpawnsTill = DateTime.Now;
        private DateTime noRound3SpawnsTill = DateTime.Now;

        private int currentNumRound1Spawns = 0;
        private int currentNumRound2Spawns = 0;
        private int currentNumRound3Spawns = 0;

        private int maxRound1Spawns = 6;
        private int maxRound2Spawns = 6;
        private int maxRound3Spawns = 6;

        List<Creature> templateCreatures = new List<Creature>();

        //Wave 1
        //341, 346, 352, 343, 349, 351

        //Wave 2
        //2382, 2383, 2384, 2385, 2386, 2387

        //Wave 3
        //2401, 2402, 2410, 2405, 2411, 2400 

        public List<int> getWaveSpawnIds(int wave)
        {
            List<int> result = new List<int>();

            if (wave == 1)
            {
                result.Add(341);
                result.Add(346);
                result.Add(352);
                result.Add(343);
                result.Add(349);
                result.Add(351);
            }
            else if (wave == 2)
            {
                result.Add(2382);
                result.Add(2383);
                result.Add(2384);
                result.Add(2385);
                result.Add(2386);
                result.Add(2387);
            }
            else if (wave == 3)
            {
                result.Add(2401);
                result.Add(2402);
                result.Add(2410);
                result.Add(2405);
                result.Add(2411);
                result.Add(2400);
            }

            return result;
        }

        private MapItem getRandomMapItem()
        {
            List<Point> hiddenList = CreatureAI.FindHidden(this, currentMapItem.mapItemsWithin4, true);

            List<MapItem> availableMapItems = new List<MapItem>();
            foreach (MapItem mapItem in currentMapItem.mapItemsWithin4)
            {
                if (mapItem.Motion > 0 && CreatureAI.isHidden(mapItem.MapX, mapItem.MapY, hiddenList) == false)
                    availableMapItems.Add(mapItem);
            }

            if (availableMapItems.Count == 0)
                return null;

            return availableMapItems[Managers.GameHandler.random.Next(availableMapItems.Count)];
        }

        private MapItem spawnCreature(int wave, int sequence)
        {
            CreatureSpawn newCreature = new CreatureSpawn(Managers.GameHandler);

            int creatureDbId = getWaveSpawnIds(wave)[sequence];

            newCreature.copyFrom(Managers.GameHandler.AllCreatures[creatureDbId]);

            newCreature.CreatureID = Managers.GameHandler.ItemIDGen.GetCreatureUID();

            newCreature.ResetCreature();

            MapItem spawnMapItem = getRandomMapItem();
            if (spawnMapItem != null)
            {
                newCreature.SetPosition(spawnMapItem);
                spawnMapItem.CreaturesBases.Add(newCreature);

                newCreature.creatureAI.Timer_CreatureRound.Start();
                newCreature.Timer_Regen.Start();

                newCreature.ID = -1;

                newCreature.WanderMax_E = -1;
                newCreature.WanderMax_N = -1;
                newCreature.WanderMax_S = -1;
                newCreature.WanderMax_W = -1;

                newCreature.Respawn_Min = -1;

                //15 Minutes.
                newCreature.StartLifespanTimer(15 * 60 * 1000);
            }

            return spawnMapItem;
        }

        private void checkSpawns()
        {
            LockItem lockItem = Managers.GameHandler.GetLockItem(MapID, Instance);
            lock (lockItem.LockObj)
            {
                //CHECK IF WE'RE IN A VALID STATE TO CONTINUE EXECUTION/////////////////////////

                //System.Reflection.MethodBase currentMethodBase = System.Reflection.MethodBase.GetCurrentMethod();
                //Delegate currentMethodDelegate = Delegate.CreateDelegate(currentMethodBase.GetType(), this, currentMethodBase.Name);

                //Create a delegate for this method incase it cant be run right now
                Action thisMethod = (Action)checkSpawns;
                //Record this method's arguments
                Object[] thisMethodArgs = { null };
                //Pass the delegate and args when we check if we're mid map transfer. If yes, they will be recorded and run again automatically.
                if (isChangingMaps(thisMethod, thisMethodArgs) == true)
                    return;

                //A map transfer happened, but its already complete. Immediately re-run this method on a different thread. 
                //We need to use a different thread because otherwise the current thread would lock 2 maps possibly resulting in a deadlock.
                if (MapID != lockItem.MapID)
                {
                    thisMethod.BeginInvoke(null, null);
                    return;
                }
                //STATE IS VALID, CONTINUE EXECUTION///////////////////////////////////////////

                if (HP < 1)
                    return;

                List<MapItem> mapItemsToUpdate = new List<MapItem>();

                if (noRound1SpawnsTill < DateTime.Now)
                {
                    if (HP < MaxHP * .75 && currentNumRound1Spawns < maxRound1Spawns)
                    {
                        currentNumRound1Spawns++;
                        
                        if (currentNumRound1Spawns == 1)
                        {
                            Message msg = new Message();
                            msg.CreatureID = this.CreatureID;
                            msg.Text = "Frogs begin emerging from the water!";
                            msg.Type = "damaged";

                            this.MessageBroadcast(currentMapItem.mapItemsWithin4, msg, false);

                        }

                        MapItem newSpawnMapItem = spawnCreature(1, currentNumRound1Spawns - 1);
                        if (newSpawnMapItem != null && mapItemsToUpdate.Contains(newSpawnMapItem) == false)
                            mapItemsToUpdate.Add(newSpawnMapItem);


                        //Spawn a 2nd
                        if (currentNumRound1Spawns < maxRound1Spawns)
                        {
                            currentNumRound1Spawns++;

                            newSpawnMapItem = spawnCreature(1, currentNumRound1Spawns - 1);
                            if (newSpawnMapItem != null && mapItemsToUpdate.Contains(newSpawnMapItem) == false)
                                mapItemsToUpdate.Add(newSpawnMapItem);
                        }

                        //all creatures spawned, reset
                        if (currentNumRound1Spawns == maxRound1Spawns)
                        {
                            currentNumRound1Spawns = 0;
                            noRound1SpawnsTill = DateTime.Now.AddMinutes(15);
                        }
                    }
                }

                if (noRound2SpawnsTill < DateTime.Now)
                {
                    if (HP < MaxHP * .50 && currentNumRound2Spawns < maxRound2Spawns)
                    {
                        currentNumRound2Spawns++;

                        if (currentNumRound2Spawns == 1)
                        {
                            Message msg = new Message();
                            msg.CreatureID = this.CreatureID;
                            msg.Text = "Sentinels begin emerging from the rocks!";
                            msg.Type = "damaged";

                            this.MessageBroadcast(currentMapItem.mapItemsWithin4, msg, false);
                        }

                        MapItem newSpawnMapItem = spawnCreature(2, currentNumRound2Spawns - 1);
                        if (newSpawnMapItem != null && mapItemsToUpdate.Contains(newSpawnMapItem) == false)
                            mapItemsToUpdate.Add(newSpawnMapItem);


                        //Spawn a 2nd
                        if (currentNumRound2Spawns < maxRound2Spawns)
                        {
                            currentNumRound2Spawns++;

                            newSpawnMapItem = spawnCreature(2, currentNumRound2Spawns - 1);
                            if (newSpawnMapItem != null && mapItemsToUpdate.Contains(newSpawnMapItem) == false)
                                mapItemsToUpdate.Add(newSpawnMapItem);
                        }

                        //all creatures spawned, reset
                        if (currentNumRound2Spawns == maxRound2Spawns)
                        {
                            currentNumRound2Spawns = 0;
                            noRound2SpawnsTill = DateTime.Now.AddMinutes(15);
                        }
                    }
                }

                if (noRound3SpawnsTill < DateTime.Now)
                {
                    if (HP < MaxHP * .25 && currentNumRound3Spawns < maxRound3Spawns)
                    {
                        currentNumRound3Spawns++;

                        if (currentNumRound3Spawns == 1)
                        {
                            Message msg = new Message();
                            msg.CreatureID = this.CreatureID;
                            msg.Text = "Sprites begin emerging from the water!";
                            msg.Type = "damaged";

                            this.MessageBroadcast(currentMapItem.mapItemsWithin4, msg, false);
                        }

                        MapItem newSpawnMapItem = spawnCreature(3, currentNumRound3Spawns - 1);
                        if (newSpawnMapItem != null && mapItemsToUpdate.Contains(newSpawnMapItem) == false)
                            mapItemsToUpdate.Add(newSpawnMapItem);


                        //Spawn a 2nd
                        if (currentNumRound3Spawns < maxRound3Spawns)
                        {
                            currentNumRound3Spawns++;

                            newSpawnMapItem = spawnCreature(3, currentNumRound3Spawns - 1);
                            if (newSpawnMapItem != null && mapItemsToUpdate.Contains(newSpawnMapItem) == false)
                                mapItemsToUpdate.Add(newSpawnMapItem);
                        }

                        //all creatures spawned, reset
                        if (currentNumRound3Spawns == maxRound3Spawns)
                        {
                            currentNumRound3Spawns = 0;
                            noRound3SpawnsTill = DateTime.Now.AddMinutes(15);
                        }
                    }
                }

                if (mapItemsToUpdate.Count > 0)
                {
                    List<Character> charactersToUpdate = currentMapItem.getCharactersWithin8();

                    foreach (Character character in charactersToUpdate)
                        character.AddMapItems(mapItemsToUpdate, false);
                }

            }
        }

    }
}
